package com.qaml.mes.device.domain.service;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.earth.except.error.BusinessException;
import com.earth.page.PageResponse;
import com.earth.user.AuthSsoContext;
import com.qaml.mes.device.api.CheckUpkeepInfoService;
import com.qaml.mes.device.api.CheckUpkeepItemService;
import com.qaml.mes.device.api.CheckUpkeepUserService;
import com.qaml.mes.device.dao.CheckUpkeepInfoDO;
import com.qaml.mes.device.dao.CheckUpkeepItemDO;
import com.qaml.mes.device.dao.CheckUpkeepUserDO;
import com.qaml.mes.device.dao.EqpInfoDO;
import com.qaml.mes.device.dto.eqp.CheckUpkeepInfoListDTO;
import com.qaml.mes.device.enums.DeletedEnum;
import com.qaml.mes.device.repository.CheckUpkeepInfoRepository;
import com.qaml.mes.device.repository.CheckUpkeepItemRepository;
import com.qaml.mes.device.repository.CheckUpkeepUserRepository;
import com.qaml.mes.device.repository.EqpInfoRepository;
import com.qaml.mes.device.domain.convert.CheckUpkeepInfoConvert;
import com.qaml.mes.device.domain.convert.CheckUpkeepItemConvert;
import com.qaml.mes.device.domain.convert.CheckUpkeepUserConvert;
import com.qaml.mes.device.dto.eqp.CheckUpkeepInfoDTO;
import com.qaml.mes.device.dto.eqp.CheckUpkeepItemDTO;
import com.qaml.mes.device.dto.eqp.CheckUpkeepUserDTO;
import com.qaml.mes.device.enums.BizErrorEnums;
import com.qaml.mes.device.enums.CheckUpkeepUserTypeEnum;
import com.qaml.mes.device.enums.UseStatusEnum;
import com.qaml.mes.device.vo.eqp.CheckUpkeepInfoVO;
import com.qaml.mes.device.vo.eqp.CheckUpkeepItemVO;
import com.qaml.mes.device.vo.eqp.CheckUpkeepUserVO;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 检保信息表 服务实现类
 * </p>
 *
 * @author leikai
 * @since 2024-02-27
 */
@Service
public class CheckUpkeepInfoServiceImpl implements CheckUpkeepInfoService {

    private static final String CHECK_UPKEEP_ID_PREFIX = "JBXM-";

    @Resource
    private CheckUpkeepInfoRepository checkUpkeepInfoRepository;

    @Resource
    private CheckUpkeepUserRepository checkUpkeepUserRepository;

    @Resource
    private CheckUpkeepItemRepository checkUpkeepItemRepository;

    @Resource
    CheckUpkeepItemService checkUpkeepItemService;

    @Resource
    CheckUpkeepUserService checkUpkeepUserService;

    @Resource
    private EqpInfoRepository eqpInfoRepository;


    /**
     * 保存或更新检保信息
     *
     * @param checkUpkeepInfoDTO 检保信息DTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(CheckUpkeepInfoDTO checkUpkeepInfoDTO) {
        List<CheckUpkeepItemDTO> checkUpkeepItemDTOList = checkUpkeepInfoDTO.getCheckUpkeepItemDTOList();
        if (CollectionUtils.isEmpty(checkUpkeepItemDTOList)) {
            throw new BusinessException(BizErrorEnums.CHECK_ITEM_ALREADY_NULL);
        }
        // 校验人员
        checkCorrelationUser(checkUpkeepInfoDTO);
        // 将检保信息DTO转DO
        CheckUpkeepInfoDO checkUpkeepInfoDO = CheckUpkeepInfoConvert.INSTANCE.saveDTO(checkUpkeepInfoDTO);
        checkUpkeepInfoDO.setTenantId(AuthSsoContext.tenantId());
        try {
            if (StringUtils.isNotBlank(checkUpkeepInfoDO.getId())) {
                // 更新检保项目信息
                checkUpkeepInfoRepository.update(checkUpkeepInfoDO);
            } else {
                // 生成检保项目编号
                checkUpkeepInfoDO.setCheckUpkeepId(CHECK_UPKEEP_ID_PREFIX + RandomUtils.nextInt(10000000, 99999999));
                checkUpkeepInfoRepository.save(checkUpkeepInfoDO);
                // 如果出现唯一键冲突，抛出业务异常： 检保项目信息已存在
            }
        } catch (DuplicateKeyException e) {
            throw new BusinessException(BizErrorEnums.CHECK_ITEM_ALREADY_EXISTS);
        }
        checkUpkeepUserRepository.deleteByCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
        checkUpkeepItemRepository.deleteByCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
        // 更新检保条目信息
        if (!CollectionUtils.isEmpty(checkUpkeepItemDTOList)) {
            List<CheckUpkeepItemDO> checkUpkeepItemDOS = CheckUpkeepItemConvert.INSTANCE.dto2DOList(checkUpkeepItemDTOList);
            checkUpkeepItemDOS.forEach(checkUpkeepItemDO -> {    // 设备编码
                checkUpkeepItemDO.setCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
                checkUpkeepItemDO.setTenantId(AuthSsoContext.tenantId());
            });
            checkUpkeepItemRepository.saveBatch(checkUpkeepItemDOS);
        }
        //  更新检保用户信息
        List<CheckUpkeepUserDTO> checkUpkeepUserDTOList = getCheckUpkeepUserDTOList(checkUpkeepInfoDTO);
        //  如果检保用户信息不为空，则 删除原有信息，然后保存
        if (!checkUpkeepUserDTOList.isEmpty()) {
            List<CheckUpkeepUserDO> checkUpkeepUserDOS = CheckUpkeepUserConvert.INSTANCE.dto2DOList(checkUpkeepUserDTOList);
            checkUpkeepUserDOS.forEach(checkUpkeepUserDO -> {
                checkUpkeepUserDO.setTenantId(AuthSsoContext.tenantId());
                checkUpkeepUserDO.setCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
            });
            checkUpkeepUserRepository.saveBatchByFor(checkUpkeepUserDOS);
        }
    }

    private void checkCorrelationUser(CheckUpkeepInfoDTO checkUpkeepInfoDTO) {

        if (CollectionUtils.isEmpty(checkUpkeepInfoDTO.getCheckUpkeepUserDTOList()) || CollectionUtils.isEmpty(checkUpkeepInfoDTO.getRecheckCheckUpkeepDTOList())) {
            throw new BusinessException(BizErrorEnums.CHECK_UPKEEP_USER_NOT_NULL);
        }
        for (CheckUpkeepUserDTO checkUpkeepUserDTO : checkUpkeepInfoDTO.getRecheckCheckUpkeepDTOList()) {
            Set<String> userIds = checkUpkeepInfoDTO.getCheckUpkeepUserDTOList().stream().map(CheckUpkeepUserDTO::getUserId).collect(Collectors.toSet());
            if (userIds.contains(checkUpkeepUserDTO.getUserId())) {
                throw new BusinessException(BizErrorEnums.RECHECK_CHECK_CHECK_UPKEEP_USER_DIS_AFFINITY);
            }
        }
    }

    private static List<CheckUpkeepUserDTO> getCheckUpkeepUserDTOList(CheckUpkeepInfoDTO checkUpkeepInfoDTO) {
        List<CheckUpkeepUserDTO> checkUpkeepUserDTOList = new ArrayList<>();

        List<CheckUpkeepUserDTO> checkUserList = checkUpkeepInfoDTO.getCheckUpkeepUserDTOList();
        if (checkUserList != null && !checkUserList.isEmpty()) {
            checkUserList.forEach(checkUpkeepUserDTO -> {
                checkUpkeepUserDTO.setPersonType(CheckUpkeepUserTypeEnum.CHECK.getType());
            });
            checkUpkeepUserDTOList.addAll(checkUserList);
        }

        List<CheckUpkeepUserDTO> recheckUserList = checkUpkeepInfoDTO.getRecheckCheckUpkeepDTOList();
        if (recheckUserList != null && !recheckUserList.isEmpty()) {
            recheckUserList.forEach(checkUpkeepUserDTO -> {
                checkUpkeepUserDTO.setPersonType(CheckUpkeepUserTypeEnum.RECHECK.getType());
            });
            checkUpkeepUserDTOList.addAll(recheckUserList);
        }

        List<CheckUpkeepUserDTO> archivistUserList = checkUpkeepInfoDTO.getArchivistCheckUpkeepUserDTOList();
        if (archivistUserList != null && !archivistUserList.isEmpty()) {
            archivistUserList.forEach(checkUpkeepUserDTO -> {
                checkUpkeepUserDTO.setPersonType(CheckUpkeepUserTypeEnum.ARCHIVIST.getType());
            });
            checkUpkeepUserDTOList.addAll(archivistUserList);
        }
        return checkUpkeepUserDTOList;
    }


    /**
     * 根据checkUpkeepId删除
     *
     * @param checkUpkeepId
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByCheckUpkeepId(String checkUpkeepId) {
        // 1,获取检保项目信息
        CheckUpkeepInfoDO checkUpkeepInfoDO = checkUpkeepInfoRepository.getById(checkUpkeepId);
        // 添加判断
        if (checkUpkeepInfoDO == null) {
            return Boolean.FALSE;
        }
        // 1.删除与检保项目有关的检保条目信息
        checkUpkeepItemService.deleteDataByCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
        // 2.删除与检保项目有关的检保用户信息
        checkUpkeepUserService.deleteDataByCheckUpkeepId(checkUpkeepInfoDO.getCheckUpkeepId());
        CheckUpkeepInfoDO update = new CheckUpkeepInfoDO();
        update.setId(checkUpkeepId);
        update.setIsDeleted(DeletedEnum.YES.getCode());
        checkUpkeepInfoRepository.update(update);
        return Boolean.TRUE;
    }

    /**
     * 根据checkUpkeepId查询详情
     *
     * @param checkUpkeepId
     * @return
     */
    @Override
    public CheckUpkeepInfoVO getByCheckUpkeepId(String checkUpkeepId) {
        // 获取检保项目基本信息
        CheckUpkeepInfoDO checkUpkeepInfoDO = checkUpkeepInfoRepository.getBycheckUpkeepId(checkUpkeepId);
        if (checkUpkeepInfoDO == null) {
            return null;
        }
        // DO -->VO
        CheckUpkeepInfoVO checkUpkeepInfoVO = CheckUpkeepInfoConvert.INSTANCE.do2VO(checkUpkeepInfoDO);

        // 获取检保用户信息
        List<CheckUpkeepUserVO> checkUpUserVOList = checkUpkeepUserService.getCheckUpkeepUserVOList(checkUpkeepId, CheckUpkeepUserTypeEnum.CHECK.getType());
        // 获取复核用户信息
        List<CheckUpkeepUserVO> recheckUserVOList = checkUpkeepUserService.getCheckUpkeepUserVOList(checkUpkeepId, CheckUpkeepUserTypeEnum.RECHECK.getType());
        // 获取归档用户信息
        List<CheckUpkeepUserVO> auditUserVOList = checkUpkeepUserService.getCheckUpkeepUserVOList(checkUpkeepId, CheckUpkeepUserTypeEnum.ARCHIVIST.getType());

        // 添加
        checkUpkeepInfoVO.setCheckUserVOList(checkUpUserVOList);
        checkUpkeepInfoVO.setRecheckUserVOList(recheckUserVOList);
        checkUpkeepInfoVO.setAuditUserVOList(auditUserVOList);

        // 获取检保项目条目信息
        List<CheckUpkeepItemVO> checkUpkeepItemVOList = checkUpkeepItemService.getCheckUpkeepItemVOList(checkUpkeepId);
        checkUpkeepInfoVO.setCheckUpkeepItemVOList(checkUpkeepItemVOList);

        return checkUpkeepInfoVO;
    }


    /**
     * 列表查询
     *
     * @param checkUpkeepInfoListDTO
     * @return
     */

    @Override
    public PageResponse<CheckUpkeepInfoVO> getCheckUpkeepInfoVOList(CheckUpkeepInfoListDTO checkUpkeepInfoListDTO) {

        //  1,查询分页对象
        IPage<CheckUpkeepInfoDO> page = checkUpkeepInfoRepository.page(checkUpkeepInfoListDTO.getPage(), checkUpkeepInfoListDTO.getPageSize(), checkUpkeepInfoListDTO);
        //  2,如果分页对象的记录列表 不为空
        if (page == null || CollectionUtils.isEmpty(page.getRecords())) {
            // 3. 如果分页对象的记录为空
            return new PageResponse<>(0, null, checkUpkeepInfoListDTO);
        }
        // 4,将查询得到的结果转换为VO
        List<CheckUpkeepInfoVO> checkUpkeepInfoVOList = CheckUpkeepInfoConvert.INSTANCE.dos2VOS(page.getRecords());

        // 查询所有的人员信息
        // 获取 所有的检保项目id-->checkUpkeepIds
        List<String> checkUpkeepIds = checkUpkeepInfoVOList.stream().map(CheckUpkeepInfoVO::getCheckUpkeepId).collect(Collectors.toList());
        // 根据checkUpkeepIds和type 查询所有的人员信息
        List<CheckUpkeepUserDO> checkUpkeepUserDOS = checkUpkeepUserRepository.getCheckUserByCheckUpkeepIds(checkUpkeepIds, null);
        Map<String, List<CheckUpkeepUserDO>> userMap;
        // 将查询到的人员进行分组   -- 根据不同的检保项目编号
        if (!CollectionUtils.isEmpty(checkUpkeepUserDOS)) {
            userMap = checkUpkeepUserDOS.stream().collect(Collectors.groupingBy(CheckUpkeepUserDO::getCheckUpkeepId));
        } else {
            userMap = new HashMap<>();
        }


        //  遍历 checkUpkeepInfoVOList（所有检保项目） 将对应的检保人员等拼接到每一条数据中
        checkUpkeepInfoVOList.forEach(checkUpkeepInfoVO -> {
            if (checkUpkeepInfoVO == null) {
                return;
            }
            List<CheckUpkeepUserDO> checkUpkeepUserDOList = userMap.get(checkUpkeepInfoVO.getCheckUpkeepId());

            // 判断每条数据对应的人员是否为空
            if (checkUpkeepUserDOList != null) {
                // 检保人员
                List<CheckUpkeepUserDO> checkList = checkUpkeepUserDOList.stream()
                        .filter(checkUpkeepUserDO -> checkUpkeepUserDO.getPersonType().equals(CheckUpkeepUserTypeEnum.CHECK.getType()))
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(checkList)) {
                    List<CheckUpkeepUserVO> voList = CheckUpkeepUserConvert.INSTANCE.toVOList(checkList);
                    checkUpkeepInfoVO.setCheckUserVOList(voList);
                }
                // 审核人员
                List<CheckUpkeepUserDO> recheckList = checkUpkeepUserDOList.stream()
                        .filter(checkUpkeepUserDO -> checkUpkeepUserDO.getPersonType().equals(CheckUpkeepUserTypeEnum.RECHECK.getType()))
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(recheckList)) {
                    List<CheckUpkeepUserVO> voList = CheckUpkeepUserConvert.INSTANCE.toVOList(recheckList);
                    checkUpkeepInfoVO.setRecheckUserVOList(voList);
                }
                // 归档人员
                List<CheckUpkeepUserDO> archiveList = checkUpkeepUserDOList.stream()
                        .filter(checkUpkeepUserDO -> checkUpkeepUserDO.getPersonType().equals(CheckUpkeepUserTypeEnum.ARCHIVIST.getType()))
                        .collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(archiveList)) {
                    List<CheckUpkeepUserVO> voList = CheckUpkeepUserConvert.INSTANCE.toVOList(archiveList);
                    checkUpkeepInfoVO.setAuditUserVOList(voList);
                }
            }
        });
        return new PageResponse<>(page.getTotal(), checkUpkeepInfoVOList, checkUpkeepInfoListDTO);
    }


    /**
     * 根据设备id(EqpId)修改状态
     *
     * @param eqpId
     */
    @Override
    public void saveStatus(String eqpId) {
        // 1,获取检保项目信息  --根据设备id
        List<CheckUpkeepInfoDO> checkUpkeepInfoDOS = checkUpkeepInfoRepository.getByEqpId(eqpId);
        // 2,标记为已关闭  0-关闭
        for (CheckUpkeepInfoDO checkUpkeepInfoDO : checkUpkeepInfoDOS) {
            checkUpkeepInfoDO.setStatus(0);
        }
        // 3,更新检保项目状态信息
        checkUpkeepInfoRepository.updateByEqpId(checkUpkeepInfoDOS);
    }


    @Override
    public void updateStatus(String eqpId) {
        CheckUpkeepInfoDO params = new CheckUpkeepInfoDO();
        params.setStatus(UseStatusEnum.ENABLED.getType());
        List<CheckUpkeepInfoDO> checkUpkeepInfoDOS = checkUpkeepInfoRepository.getByEqpIdAndParams(eqpId, params);
        if (!CollectionUtils.isEmpty(checkUpkeepInfoDOS)) {
            for (CheckUpkeepInfoDO checkUpkeepInfoDO : checkUpkeepInfoDOS) {
                checkUpkeepInfoDO.setStatus(UseStatusEnum.DISABLED.getType());
                checkUpkeepInfoRepository.update(checkUpkeepInfoDO);
            }
        }
    }

    @Override
    public void enableEqp(String id) {
        CheckUpkeepInfoDO checkUpkeepInfoDO = checkUpkeepInfoRepository.getByIdAndStatus(id, UseStatusEnum.DISABLED.getType());
        if (null == checkUpkeepInfoDO) {
            return;
        }
        EqpInfoDO eqpInfoDO = eqpInfoRepository.getById(checkUpkeepInfoDO.getEqpId());
        if (null == eqpInfoDO) {
            throw new BusinessException(500, "关联设备不存在");
        }
        if (UseStatusEnum.DISABLED.getType().equals(eqpInfoDO.getStatus())) {
            throw new BusinessException(500, "设备已关闭,不能启动！");
        }
        checkUpkeepInfoDO.setStatus(UseStatusEnum.ENABLED.getType());
        checkUpkeepInfoRepository.update(checkUpkeepInfoDO);
    }

    @Override
    public void disableEqp(String id) {
        CheckUpkeepInfoDO checkUpkeepInfoDO = checkUpkeepInfoRepository.getByIdAndStatus(id, UseStatusEnum.ENABLED.getType());
        if (null == checkUpkeepInfoDO) {
            return;
        }
        checkUpkeepInfoDO.setStatus(UseStatusEnum.DISABLED.getType());
        checkUpkeepInfoRepository.update(checkUpkeepInfoDO);
    }

}
